home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Tools / ckconfig / ckconfig.c next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  29.8 KB  |  1,331 lines

  1. /* ckconfig.c: management tool to check configuration of PP system */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/ckconfig/RCS/ckconfig.c,v 6.0 1991/12/18 20:29:03 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Tools/ckconfig/RCS/ckconfig.c,v 6.0 1991/12/18 20:29:03 jpo Rel $
  9.  *
  10.  * $Log: ckconfig.c,v $
  11.  * Revision 6.0  1991/12/18  20:29:03  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16.  
  17.  
  18. #include    "qmgr.h"
  19. #include     "util.h"
  20. #include    "chan.h"
  21. #include    "table.h"
  22. #include    "list_bpt.h"
  23. #include    "adr.h"
  24. #include    "retcode.h"
  25. #include    <sys/stat.h>
  26. #include    <pwd.h>
  27. #include    <signal.h>
  28. #include    <varargs.h>
  29. #include     <sys/wait.h>
  30.  
  31. #ifndef WEXITSTATUS
  32. #define WEXITSTATUS(x) (((union wait *)&(x)) -> w_retcode)
  33. #endif
  34.  
  35. extern struct passwd    *getpwnam(), *getpwuid();
  36. extern void    getfpath(), dsap_init();
  37.  
  38. typedef enum {
  39.     ok,
  40.     notExist,
  41.     highMode,
  42.     lowMode,
  43.     wrongOwner,
  44.     wrongGroup
  45.     } Retvals;
  46.  
  47. static Retvals     check_file();
  48. static int     check_main_vars();
  49. static int    check_dirs();
  50. static int    check_chans();
  51. static int    check_channel();
  52. static int    check_filter();
  53. static int    check_tables();
  54. static int    check_table_file();
  55. static int    check_table();
  56. static int    check_bps(), check_hdrs();
  57. static int    check_822address();
  58. static int    yesorno();
  59. static int    check_hardwired();
  60. static int    makedirectory();
  61. static int    changemode();
  62. static int    changeowner();
  63. static void    check_dsap ();
  64. static void    perrstr ();
  65. static int    pok();
  66. static int    ptabss();
  67. static int    ptabsd();
  68. static void     ckerror ();
  69. #define OPEN_MODE    0777
  70. #define CLOSED_MODE    0700
  71.  
  72. #define    DIR_MODE    0775
  73. #define EXEC_MODE    0755
  74. #define RSEXEC_MODE    0700
  75. #define TABLE_MODE    0644
  76. #define RSTABLE_MODE    0600
  77.  
  78. int    interactive,
  79.     monitoring,
  80.     verbose;
  81. extern char    *ppversion, *pptailor;
  82. extern void     sys_init();
  83.  
  84. main(argc, argv)
  85. int    argc;
  86. char    **argv;
  87. {
  88.     int    opt;
  89.     Retvals    retval;
  90.     unsigned int    fileMode = 0;
  91.     char    *myname = argv[0], prompt[BUFSIZ], owner[MAXPATHLENGTH];
  92.     extern int optind;
  93.     extern char *optarg;
  94.  
  95.     interactive = TRUE;
  96.     monitoring = FALSE;
  97.     verbose = FALSE;
  98.  
  99.     while ((opt = getopt (argc, argv, "fnvt:")) != EOF) {
  100.         switch (opt) {
  101.             case 'f':
  102.             interactive = FALSE;
  103.             break;
  104.  
  105.             case 'n':
  106.             monitoring = TRUE;
  107.             break;
  108.  
  109.             case 'v':
  110.             verbose = TRUE;
  111.             break;
  112.             case 't':
  113.             pptailor = optarg;
  114.             break;
  115.  
  116.             default:
  117.             printf("Usage: %s [-n] [-f] [-v] [-t tailorfile]\n",myname);
  118.             exit(1);
  119.             break;
  120.         }
  121.     }
  122.     retval = check_file(pptailor, 0644, 0600, &fileMode, owner);
  123.     switch (retval) {
  124.         case notExist:
  125.         perrstr("Tailor file does not exist\n\tShould be in %s\n\n",pptailor);
  126.         exit(1);
  127.         break;
  128.  
  129.         case lowMode:
  130.         perrstr("The tailor file '%s' has too low a permission mode.\n",
  131.                pptailor);
  132.         sprintf(prompt, "Change mode of %s from %o to %o",
  133.             pptailor,
  134.             fileMode,
  135.             0600);
  136.         if (yesorno(prompt) == TRUE)
  137.             changemode(pptailor, 0600);
  138.         break;
  139.  
  140.         case highMode:
  141.         perrstr("The tailor file '%s' has too high a permission mode.\n",
  142.                pptailor);
  143.         sprintf(prompt, "Change mode of %s from %o to %o",
  144.             pptailor,
  145.             fileMode,
  146.             0644);
  147.         if (yesorno(prompt) == TRUE)
  148.             changemode(pptailor, 0644);
  149.         break;
  150.  
  151.         default:
  152.         break;
  153.     }
  154.     pok("Tailor file",pptailor);
  155.     tai_seterrorhandler (ckerror);
  156.     sys_init (myname);
  157.     (void) signal (SIGPIPE, SIG_DFL);
  158.  
  159.     check_dsap ();
  160.     check_main_vars();
  161.     check_dirs();
  162.     check_chans();
  163.     check_tables();  
  164.     check_hardwired();
  165. }
  166.  
  167. static void ckerror (str)
  168. char *str;
  169. {
  170.     fprintf (stderr, "%s", str);
  171. }
  172.  
  173. /*   */
  174. extern    char    *loc_dom_mta,
  175.         *loc_dom_site,
  176.         *loc_or,
  177.         *x400_mta,
  178.         *postmaster,
  179.         *pplogin,
  180.         *pptsapd_addr,
  181.         *mboxname,
  182.         *qmgr_hostname;
  183. extern int    max_hops, max_loops;
  184.  
  185. extern LIST_BPT    *bodies_all, *headers_all;
  186. int        ppuid = 0, ppgid = 0;
  187.  
  188. static int check_main_vars()
  189. /* really just print them out */
  190. {
  191.     struct passwd    *password = NULL;
  192.     LIST_BPT    *ix;
  193.     RP_Buf        rp;
  194.     ADDR        *ad;
  195.     AEI        aei;
  196.     register struct PSAPaddr *pa;
  197.     
  198.     if (str2paddr (pptsapd_addr) == NULLPA) 
  199.         perrstr ("Invalid pptsapd address '%s'\n\n",
  200.               pptsapd_addr);
  201.     else
  202.         pok("pptsapd address", pptsapd_addr);
  203.  
  204.     if ((aei = _str2aei (qmgr_hostname, "pp qmgr", 
  205.                  QMGR_CTX_OID, 0, dap_user,
  206.                  dap_passwd)) == NULLAEI)
  207.         if ((aei = _str2aei (qmgr_hostname, "pp-qmgr",
  208.                      QMGR_CTX_OID, 
  209.                      0, dap_user, dap_passwd)) != NULLAEI)
  210.             perrstr ("Old form of AEI \"pp-qmgr\" %s\n",
  211.                   "change to \"pp qmgr\" in isoentites");
  212.  
  213.     if (aei == NULLAEI)
  214.         perrstr ("Invalid qmgr hostname: %s-pp qmgr unknown application-entity\n\n",
  215.               qmgr_hostname);
  216.     else if ((pa = aei2addr(aei)) == NULLPA)
  217.         perrstr ("Invalid qmgr hostname '%s': address translation failed\n\n",
  218.               qmgr_hostname);
  219.     else
  220.         pok ("qmgr hostname", qmgr_hostname);
  221.  
  222.  
  223.     if ((password = getpwnam(pplogin)) == NULL)
  224.         perrstr("Cannot access password entry for PP login '%s'\n\n",pplogin);
  225.     else if (verbose == TRUE) {
  226.         ptabss("PP login", pplogin);
  227.         ptabsd("uid",    password->pw_uid);
  228.         ptabsd("guid",password->pw_gid);
  229.         pnewline();
  230.     }
  231.     if (password != NULL) {
  232.         ppuid = password->pw_uid;
  233.         ppgid = password->pw_gid;
  234.     }
  235.  
  236.     pok("Local Mta",loc_dom_mta);
  237.     pok("Local Site", loc_dom_site);
  238.     pok("Local O/R address",loc_or);
  239.     pok("X400 MTA name", x400_mta);
  240.  
  241.     if (max_hops <= 0 || max_hops >= 100)
  242.         perrstr("WARNING: Maximum number of hops (trace fields) is set to %d",
  243.              (char *) max_hops);
  244.     else if (verbose == TRUE) {
  245.         char    buf[BUFSIZ];
  246.         (void) sprintf(buf, "%d", max_hops);
  247.         pok("Maximum hops", buf);
  248.     }
  249.  
  250.     if (max_loops <= 0 || max_loops >= 100)
  251.         perrstr("WARNING: Maximum nmber of local loops is set to %d",
  252.              (char *) max_loops);
  253.     else if (verbose == TRUE) {
  254.         char    buf[BUFSIZ];
  255.         (void) sprintf(buf, "%d", max_loops);
  256.         pok("Maximum loops", buf);
  257.     }
  258.         
  259.     pok("Mailbox name", mboxname);
  260.  
  261.     ad = adr_new(postmaster, AD_822_TYPE, 0);
  262. #ifdef UKORDER
  263.     if (rp_isbad(ad_parse(ad, &rp, CH_UK_PREF))) 
  264. #else
  265.     if (rp_isbad(ad_parse(ad, &rp, CH_USA_PREF))) 
  266. #endif
  267.         perrstr("Postmaster '%s' is an invalid address (reason = '%s').\n",
  268.              postmaster,
  269.              ad->ad_parse_message);
  270.     else
  271.         pok("Post Master", postmaster);
  272.     adr_free(ad);
  273.  
  274.     check_822address("postmaster");
  275.     if (verbose == TRUE) check_822address("support");
  276.     if (verbose == TRUE) check_822address("operator");
  277.     if (verbose == TRUE) check_822address("admin");
  278.  
  279.     /* print list of body types */
  280.     if (bodies_all == NULLIST_BPT)
  281.         perrstr("System does not recognise any body parts\n\n","");
  282.     else if (verbose == TRUE) {
  283.  
  284.         ix = bodies_all;
  285.         printf("The system reconises the following body parts :-\n");
  286.         while (ix != NULLIST_BPT) {
  287.             ptabss("",ix->li_name);
  288.             ix = ix->li_next;
  289.         }
  290.         pnewline();
  291.     }
  292. }
  293.     
  294. /*   */
  295.  
  296. typedef struct direntry {
  297.     char        **fldirname;
  298.     char        *name;
  299.     int        maxmode, minmode;
  300. } Direntry;
  301.  
  302. extern char    *quedfldir,
  303.         *cmddfldir,
  304.         *chndfldir,
  305.         *formdfldir,
  306.         *tbldfldir,
  307.         *logdfldir,
  308.         *ppdbm,
  309.         *wrndfldir;
  310.  
  311. /*    0700 = rwx------
  312.     0777 = rwxrwxrwx
  313.     0711 = rwx--x--x
  314.     0775 = rwxrwxr-x */
  315.  
  316. struct direntry dirs[] = {
  317.     &quedfldir, "queue", 0700, 0700,
  318.     &cmddfldir, "commands", 0775, 0711,
  319.     &chndfldir, "channels", 0775, 0711,
  320.     &formdfldir, "format", 0775, 0711,
  321.     &tbldfldir, "table", 0775, 0711,
  322.     &logdfldir, "logging", 0775, 0711,
  323.     &wrndfldir, "warnings", 0775, 0711,
  324.     0, 0
  325.     };
  326.  
  327. /*   */
  328. /* file and directory checking routines */
  329. static Retvals check_file(name, himode, lomode, pfileMode, owner)
  330. char        *name;
  331. unsigned int    himode, lomode, *pfileMode;
  332. char        *owner;
  333. {
  334.     struct stat     statbuf;
  335.     struct passwd    *temp;
  336.  
  337.     if (stat(name, &statbuf) != OK) 
  338.         return notExist;
  339.     if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
  340.         *pfileMode = statbuf.st_mode & ~(S_IFMT|S_ISUID|S_ISGID|S_ISVTX);
  341.     else
  342.         *pfileMode = statbuf.st_mode & ~S_IFMT;
  343.     if (*pfileMode & lomode != lomode)
  344.         return lowMode;
  345.     if (((*pfileMode) & (~himode)) != 0)
  346.         return highMode;
  347.     if (statbuf.st_uid != ppuid) {
  348.         if ((temp = getpwuid(statbuf.st_uid)) == NULL) {
  349.             if (verbose == TRUE)
  350.                 printf("**** ");
  351.             printf("Unknown uid '%o' owns %s.\n",
  352.                    statbuf.st_uid,
  353.                    name);
  354.             owner[0] = '\0';
  355.         } else {
  356.             (void) sprintf(owner, "%s", temp->pw_name);    
  357.         }
  358.         return wrongOwner;
  359.     }
  360.     return ok;
  361. }
  362.  
  363. static int check_directory(dir)
  364. struct direntry    *dir;
  365. {
  366.     char    prompt[BUFSIZ], owner[MAXPATHLENGTH];
  367.     Retvals    retval;
  368.     unsigned int    fileMode = 0;
  369.  
  370.     while ((retval = check_file(*(dir->fldirname), 
  371.                     (unsigned int) dir->maxmode,
  372.                     (unsigned int) dir->minmode,
  373.                     &fileMode, 
  374.                     owner)) != ok) {
  375.         switch    (retval) {
  376.  
  377.             case notExist:
  378.             perrstr("The %s directory does not exist.\n", 
  379.                    dir->name);
  380.             sprintf(prompt, "Make directory %s with mode %o",
  381.                 *(dir->fldirname), dir->maxmode);
  382.             if (yesorno(prompt) == TRUE) 
  383.                 makedirectory(*(dir->fldirname), dir->maxmode);
  384.             else 
  385.                 return;
  386.             break;
  387.             
  388.             case highMode:
  389.             if (dir -> maxmode == dir -> minmode)
  390.                 perrstr("The directory '%s' has the wrong permission modes.\n",
  391.                      *(dir->fldirname));
  392.             else
  393.                 perrstr("The directory '%s' has too high a permission mode.\n",
  394.                      *(dir->fldirname));
  395.             sprintf(prompt, "Change mode of %s from %o to %o",
  396.                 *(dir->fldirname),
  397.                 fileMode,
  398.                 dir->maxmode);
  399.             if (yesorno(prompt) == TRUE)
  400.                 changemode(*(dir->fldirname), dir->maxmode);
  401.             else
  402.                 return;
  403.             break;
  404.  
  405.             case lowMode:
  406.             if (dir -> maxmode == dir -> minmode)
  407.                 perrstr("The directory '%s' has the wrong permission modes.\n",
  408.                      *(dir->fldirname));
  409.             else
  410.                 perrstr("The directory '%s' has too low a permission mode.\n",
  411.                      *(dir->fldirname));
  412.  
  413.             sprintf(prompt, "Change mode of %s from %o to %o",
  414.                 *(dir->fldirname),
  415.                 fileMode,
  416.                 dir->minmode);
  417.             if (yesorno(prompt) == TRUE)
  418.                 changemode(*(dir->fldirname), dir->minmode);
  419.             else
  420.                 return;
  421.             break;
  422.  
  423.             case wrongOwner:
  424.             perrstr("The directory '%s' is not owned by the PP uid.\n",
  425.                    *(dir->fldirname));
  426.             if (owner[0] == '\0')
  427.                 (void) sprintf(prompt,
  428.                            "Change owner of %s to %s",
  429.                            *(dir->fldirname),
  430.                            pplogin);
  431.             else
  432.                 (void) sprintf(prompt,
  433.                            "Change owner of %s from %s to %s",
  434.                            *(dir->fldirname),
  435.                            owner,
  436.                            pplogin);
  437.             if (yesorno(prompt) == TRUE)
  438.                 changeowner(*(dir->fldirname), 
  439.                         ppuid,
  440.                         ppgid);
  441.             else
  442.                 return;
  443.             break;
  444.  
  445.             default:
  446.             break;
  447.         }
  448.     }
  449.     pok(dir->name, *(dir->fldirname));
  450. }
  451.  
  452. static int check_dirs()
  453. {
  454.     int i = 0;
  455.     char    *ix;
  456.     struct direntry temp;
  457.     char    fullpath[MAXPATHLENGTH];
  458.     if (verbose == TRUE)
  459.         printf("Checking the various directories\n\n");
  460.  
  461.     while (dirs[i].name != NULL)
  462.         check_directory(&(dirs[i++]));
  463.     /* special cases */
  464.     /* ppdbm */
  465.     if ((ix = rindex(ppdbm, '/')) != NULL) {
  466.         *ix = '\0';
  467.         if (verbose == TRUE)
  468.             printf("Checking the directory for ppdbm file exist\n");
  469.         temp.fldirname = &ppdbm;
  470.         temp.name = "dbm";
  471.         temp.maxmode = 0775;
  472.         temp.minmode = 0711;
  473.         check_directory(&temp);
  474.         *ix = '/';
  475.     }
  476. }
  477.  
  478. /*   */
  479. /* check the executables for the channels */
  480. /*   and the filter executables for the filtercontrol channels */
  481. /*   then print out some nice info */
  482.  
  483. static int    warning,
  484.         delete,
  485.         qmgr_load,
  486.         debris,
  487.         time_out;
  488.  
  489. #define    spec_chan_error    "There is no %s channel.\n"
  490. static int check_special_channels()
  491. {
  492.     if (warning == 0) 
  493.         perrstr(spec_chan_error, "warning");
  494.     if (delete == 0)
  495.         perrstr(spec_chan_error, "delete");
  496.     if (qmgr_load == 0)
  497.         perrstr(spec_chan_error, "qmgr-load");
  498.     if (debris == 0)
  499.         perrstr(spec_chan_error, "debris");
  500.     if (time_out == 0)
  501.         perrstr(spec_chan_error, "timeout");
  502. }
  503.  
  504. static int check_chans()
  505. {
  506.     CHAN    **ix = ch_all;
  507.     
  508.     warning = delete = qmgr_load = debris = time_out = 0;
  509.  
  510.     if (verbose == TRUE)
  511.         printf("\nChecking the various channels\n\n");
  512.  
  513.     while (*ix != NULL)
  514.         check_channel(*ix++);
  515.     check_special_channels();
  516. }
  517.  
  518. static char *chan_type(chan)
  519. CHAN    *chan;
  520. {
  521.     char    *str = NULLCP;
  522.     switch(chan->ch_chan_type) {
  523.         case CH_SHAPER:
  524.         str = "formatter channel";
  525.         break;
  526.         case CH_IN:
  527.         str = "listener channel";
  528.         break;
  529.         case CH_OUT:
  530.         str = "transmitter channel";
  531.         break;
  532.         case CH_BOTH:
  533.         str = "listener/transmitter channel";
  534.         break;
  535.         case CH_WARNING:
  536.         str = "warning channel";
  537.         warning = 1;
  538.         break;
  539.         case CH_DELETE:
  540.         str = "deletion channel";
  541.         delete = 1;
  542.         break;
  543.         case CH_QMGR_LOAD:
  544.         str = "loader channel";
  545.         qmgr_load = 1;
  546.         break;
  547.         case CH_DEBRIS:
  548.         str = "debris cleaning channel";
  549.         debris = 1;
  550.         break;
  551.         case CH_TIMEOUT:
  552.         str = "timeout channel";
  553.         time_out = 1;
  554.         break;
  555.         case CH_SPLITTER:
  556.         str = "splitter";
  557.         break;
  558.         default:
  559.         str = "Unknown type";
  560.         break;
  561.     }
  562.     return str;
  563. }
  564.  
  565. static int check_channel(chan)
  566. CHAN    *chan;
  567. {
  568.     struct stat statbuf;
  569.     char    fullname[MAXPATHLENGTH],
  570.         *ch_type,
  571.         *margv[100];
  572.     int    margc;
  573.     
  574.     ch_type = chan_type(chan);
  575.  
  576.     /* do checking */
  577.     if (chan->ch_progname != NULLCP) {
  578.         if ((margc = sstr2arg(chan->ch_progname, 100, margv, " \t")) < 1) {
  579.             perrstr("Unable to parse program '%s' for channel '%s'\n",
  580.                    chan->ch_progname,
  581.                    chan->ch_name);
  582.             return;
  583.         }
  584.         if (margv[0][0] == '/')
  585.             sprintf(fullname,"%s",margv[0]);
  586.         else
  587.             sprintf(fullname,"%s/%s",chndfldir,margv[0]);
  588.  
  589.         if (stat(fullname, &statbuf) != OK)
  590.             perrstr("The program %s for channel %s does not exist\n",
  591.                  fullname, chan->ch_name);
  592.         else if (!(statbuf.st_mode & S_IEXEC)) 
  593.             perrstr("The program %s for the channel %s is not executable\n",
  594.                  fullname, chan->ch_name);
  595.         else if (statbuf.st_mode & S_ISUID
  596.              && chan->ch_access != CH_MTS 
  597.              && (chan->ch_chan_type != CH_OUT 
  598.                  || chan->ch_chan_type != CH_BOTH)) {
  599.             perrstr("WARNING The program %s for the channel %s is set uid.\n",
  600.                  fullname, chan->ch_name);
  601.             if (verbose == TRUE)
  602.                 printf("**** ");
  603.             printf("Only local channels should be set uid\n");
  604.  
  605.         }
  606.         
  607.         if (chan->ch_access == CH_MTS
  608.             && (chan->ch_chan_type == CH_OUT 
  609.             || chan->ch_chan_type == CH_BOTH)) {
  610.             /* local delivery */
  611.             if (statbuf.st_uid != 0)
  612.                 perrstr("WARNING Channel '%s' is local delivery\n\tbut program '%s' isn't owned by root.\n",
  613.                      chan->ch_name,
  614.                      fullname);
  615.         } else if (statbuf.st_uid != ppuid) 
  616.             perrstr("WARNING program '%s' for channel '%s' is not owned by '%s'\n",
  617.                  fullname,
  618.                  chan->ch_name,
  619.                  pplogin);
  620.         
  621.         if (chan->ch_access == CH_MTS 
  622.             && (chan->ch_chan_type == CH_OUT || chan->ch_chan_type == CH_BOTH)
  623.             && !(statbuf.st_mode & S_ISUID)) 
  624.             perrstr("WARNING Channel '%s' is local delivery\n\tbut program '%s' isn't set uid.\n",
  625.                  chan->ch_name,
  626.                  fullname);
  627.     } else if (chan->ch_chan_type != CH_IN)
  628.         perrstr("WARNING No program given for channel %s\n",chan->ch_name);
  629.     if (chan->ch_out_info != NULL
  630.         && chan->ch_chan_type == CH_SHAPER)
  631.         /* assume is a filter control channel */
  632.         check_filter(chan->ch_name, chan->ch_out_info);
  633.  
  634.     if (chan->ch_table != NULL) 
  635.         check_table_file(chan->ch_table,0644, 0600);
  636.     
  637.     if (chan->ch_mta_table != NULL) 
  638.         check_table_file(chan->ch_mta_table,0644, 0600);
  639.  
  640.     if (chan->ch_in_table != NULL) 
  641.         check_table_file(chan->ch_in_table,0644, 0600);
  642.  
  643.     if (chan->ch_hdr_in != NULL) 
  644.         check_hdrs(chan->ch_name, chan->ch_hdr_in);
  645.  
  646.     if (chan->ch_hdr_out != NULL)
  647.         check_hdrs(chan->ch_name, chan->ch_hdr_out);
  648.  
  649.     if (chan->ch_bpt_in != NULL)
  650.         check_bps(chan->ch_name, chan->ch_bpt_in);
  651.  
  652.     if (chan->ch_bpt_out != NULL)
  653.         check_bps(chan->ch_name, chan->ch_bpt_out);
  654.  
  655.     if (chan->ch_drchan != NULLCP &&
  656.         chan->ch_chan_type != CH_BOTH &&
  657.         chan->ch_chan_type != CH_OUT)
  658.         perrstr("drchan '%s' specified for channel '%s'\n\tOnly outbound channels should have drchan specified\n",
  659.                  chan->ch_drchan, chan->ch_name);
  660.     if (chan -> ch_drchan) {
  661.         CHAN *drc = ch_nm2struct(chan -> ch_drchan);
  662.         if (drc == NULLCHAN)
  663.             perrstr ("drchan '%s' for channel %s does not exist\n",
  664.                   chan -> ch_drchan, chan -> ch_name);
  665.         else if (drc -> ch_chan_type != CH_BOTH &&
  666.              drc -> ch_chan_type != CH_OUT)
  667.             perrstr ("drchan '%s' for channel %s is not outbound type\n",
  668.                   chan -> ch_drchan, chan -> ch_name);
  669.     }
  670.     if (chan->ch_badSenderPolicy != CH_BADSENDER_STRICT
  671.         && chan->ch_chan_type != CH_BOTH
  672.         && chan->ch_chan_type != CH_IN)
  673.         perrstr("bad-sender-policy specified for channel '%s'\n\tOnly inbound channels should have bad-sender-policy specified\n",
  674.              chan->ch_name);
  675.  
  676.     if (chan->ch_out_ad_type == AD_ANY_TYPE) 
  677.         perrstr("WARNING address type set to any for channel %s.\n\tThis may cause address parsing problems.\n",chan->ch_name);
  678.     if (chan->ch_in_ad_type == AD_ANY_TYPE) 
  679.         perrstr("WARNING address type set to any for channel %s.\n\tThis may cause address parsing problems.\n",chan->ch_name);
  680.  
  681.     if (verbose == TRUE) {
  682.         /* print info */
  683.         ptabss(chan->ch_name,
  684.                (chan->ch_show == NULL) ? chan->ch_name : chan->ch_show);
  685.         if (chan->ch_progname != NULLCP)
  686.             ptabss("program", chan->ch_progname);
  687.  
  688.         if (chan->ch_drchan != NULLCP)
  689.             ptabss("drchan", chan->ch_drchan);
  690.  
  691.         ptabss("type", ch_type);
  692.  
  693.         if (chan->ch_out_info != NULL)
  694.             ptabss("filter run as", chan->ch_out_info);
  695.  
  696.         if (chan->ch_table == NULL)
  697.             ptabss("channel outbound table", "none");
  698.         else
  699.             ptabss("channel outbound table",chan->ch_table->tb_name);
  700.  
  701.         if (chan->ch_in_table == NULL)
  702.             ptabss("channel inbound table", "none");
  703.         else
  704.             ptabss("channel inbound table",chan->ch_in_table->tb_name);
  705.  
  706.         if (chan->ch_mta_table == NULL)
  707.             ptabss("channel MTA table", "none");
  708.         else
  709.             ptabss("channel MTA table",chan->ch_mta_table->tb_name);
  710.         pnewline();
  711.     }
  712. }
  713.  
  714. static int check_filter(chan, info)
  715. char    *chan,
  716.     *info;
  717. {
  718.     char    fullname[MAXPATHLENGTH],
  719.         *ix = info,
  720.         saved;
  721.     struct stat statbuf;
  722.  
  723.     while (*ix != '\0' && !isspace(*ix))
  724.         ix++;
  725.     saved = *ix;
  726.     *ix = '\0';
  727.     
  728.     if (info[0] == '/')
  729.         sprintf(fullname, "%s", info);
  730.     else
  731.         sprintf(fullname, "%s/%s",formdfldir,info);
  732.  
  733.     *ix = saved;
  734.  
  735.     if (stat(fullname, &statbuf) != OK) {
  736.         if (verbose == TRUE)
  737.             printf("**** ");
  738.         printf("The filter %s for channel %s does not exist\n",
  739.                fullname, chan);
  740.         return;
  741.     }
  742.     if (!(statbuf.st_mode & S_IEXEC)) {
  743.         if (verbose == TRUE)
  744.             printf("**** ");
  745.         printf("The filter %s for channel %s is not executable\n",
  746.                fullname, chan);
  747.         return;
  748.     }
  749. }
  750.  
  751. /*   */
  752. /* check the tables */
  753.  
  754. static int check_tables()
  755. {
  756.     Table    **ix = tb_all;
  757.  
  758.     if (verbose == TRUE)
  759.         printf("\nChecking the various tables\n\n");
  760.     while (*ix != NULL) {
  761.         check_table(*ix++);
  762.         pnewline();
  763.     }
  764. }
  765.  
  766. static int check_table_file(tbl, maxmode, minmode)
  767. Table        *tbl;
  768. int        maxmode, minmode;
  769. {
  770.     char    fullname[MAXPATHLENGTH], owner[MAXPATHLENGTH], prompt[BUFSIZ];
  771.     unsigned int    fileMode = 0;
  772.     Retvals    retval;
  773.  
  774.     if (tbl->tb_file[0] == '/')
  775.         sprintf(fullname,"%s",tbl->tb_file);
  776.     else
  777.         sprintf(fullname,"%s/%s",tbldfldir,tbl->tb_file);
  778.  
  779.     while ((retval = check_file(fullname, (unsigned int) maxmode,
  780.                     (unsigned int) minmode,
  781.                     &fileMode, owner)) != ok) {
  782.         switch (retval) {
  783.             case notExist:
  784.             perrstr("The file %s is not present for table %s\n",
  785.                  fullname, tbl->tb_name);
  786.             return;
  787.            
  788.             case highMode:
  789.             if (maxmode == minmode)
  790.                 perrstr("The table file '%s' has the wrong permission modes.\n",
  791.                      fullname);
  792.             else
  793.                 perrstr("The table file '%s' has too high a permission mode.\n",
  794.                      fullname);
  795.             sprintf(prompt, "Change mode of %s from %o to %o",
  796.                 fullname,
  797.                 fileMode,
  798.                 maxmode);
  799.             if (yesorno(prompt) == TRUE)
  800.                 changemode(fullname, maxmode);
  801.             else
  802.                 return;
  803.             break;
  804.  
  805.             case lowMode:
  806.             if (maxmode == minmode)
  807.                 perrstr("The table file '%s' has the wrong permission modes.\n",
  808.                      fullname);
  809.             else
  810.                 perrstr("The table file '%s' has too low a permission mode.\n");
  811.             
  812.             sprintf(prompt, "Change mode of %s from %o to %o",
  813.                 fullname,
  814.                 fileMode,
  815.                 minmode);
  816.             if (yesorno(prompt) == TRUE)
  817.                 changemode(fullname, minmode);
  818.             else
  819.                 return;
  820.             break;
  821.  
  822.             case wrongOwner:
  823.             perrstr("The table file '%s' is not owned by the PP uid.\n",
  824.                    fullname);
  825.             if (owner[0] == '\0')
  826.                 (void) sprintf(prompt,
  827.                            "Change owner of %s to %s",
  828.                            fullname,
  829.                            pplogin);
  830.             else
  831.                 (void) sprintf(prompt,
  832.                            "Change owner of %s from %s to %s",
  833.                            fullname,
  834.                            owner,
  835.                            pplogin);
  836.             if (yesorno(prompt) == TRUE)
  837.                 changeowner(fullname,
  838.                         ppuid,
  839.                         ppgid);
  840.             else
  841.                 return;
  842.             break;
  843.              
  844.             default:
  845.             break;
  846.         }
  847.     }
  848. }
  849.     
  850. static int check_table(tbl)
  851. Table    *tbl;
  852. {
  853.     char    fullname[MAXPATHLENGTH], owner[MAXPATHLENGTH], prompt[BUFSIZ];
  854.     unsigned int     fileMode = 0;
  855.     Retvals    retval;
  856.  
  857.     if (tbl->tb_file[0] == '/')
  858.         sprintf(fullname,"%s",tbl->tb_file);
  859.     else
  860.         sprintf(fullname,"%s/%s",tbldfldir,tbl->tb_file);
  861.  
  862.     while ((retval = check_file(fullname, 0644, 0600,
  863.                     &fileMode, owner)) != ok) {
  864.         switch (retval) {
  865.             case notExist:
  866.             perrstr("The file %s is not present for table %s\n",
  867.                  fullname, tbl->tb_name);
  868.             return;
  869.             
  870.             case highMode:
  871.             perrstr("The table file '%s' has too high a permission mode.\n",
  872.                    fullname);
  873.             sprintf(prompt, "Change mode of %s from %o to %o",
  874.                 fullname,
  875.                 fileMode,
  876.                 0644);
  877.             if (yesorno(prompt) == TRUE)
  878.                 changemode(fullname, 0644);
  879.             else
  880.                 break;
  881.             continue;
  882.  
  883.             case lowMode:
  884.             perrstr("The table file '%s' has too low a permission mode.\n",
  885.                    fullname);
  886.             sprintf(prompt, "Change mode of %s from %o to %o",
  887.                 fullname,
  888.                 fileMode,
  889.                 0600);
  890.             if (yesorno(prompt) == TRUE)
  891.                 changemode(fullname, 0600);
  892.             else
  893.                 break;
  894.             continue;
  895.  
  896.             case wrongOwner:
  897.             perrstr("The table file '%s' is not owned by the PP uid.\n",
  898.                    fullname);
  899.             if (owner[0] == '\0')
  900.                 (void) sprintf(prompt,
  901.                            "Change owner of %s to %s",
  902.                            fullname,
  903.                            pplogin);
  904.             else
  905.                 (void) sprintf(prompt,
  906.                            "Change owner of %s from %s to %s",
  907.                            fullname,
  908.                            owner,
  909.                            pplogin);
  910.             if (yesorno(prompt) == TRUE)
  911.                 changeowner(fullname,
  912.                         ppuid,
  913.                         ppgid);
  914.             else
  915.                 break;
  916.             continue;
  917.              
  918.             default:
  919.             continue;
  920.         }
  921.         break;
  922.     }
  923.  
  924.     ptabss(tbl->tb_name,tbl->tb_show);
  925.     ptabss("file",fullname);
  926.     switch (tbl->tb_flags) {
  927.         case TB_DBM:
  928.         ptabss("Storage","database");
  929.         break;
  930.         case TB_LINEAR:
  931.         ptabss("Storage", "linear");
  932.         break;
  933.         default:
  934.         ptabss("Storage","unknown option");
  935.         break;
  936.     }
  937. }
  938.  
  939. static int check_bps(channame, list)
  940. char        *channame;
  941. LIST_BPT    *list;
  942. {
  943.     LIST_BPT    *ix;
  944.  
  945.     while (list != NULL) {
  946.         ix = bodies_all;
  947.         while (ix != NULL
  948.                && strcmp(ix->li_name, list->li_name) != 0)
  949.             ix = ix->li_next;
  950.         if (ix == NULLIST_BPT)
  951.             perrstr("The channel '%s' has an unrecognised bodypart '%s'.\n",
  952.                  channame,
  953.                  list->li_name);
  954.         list = list->li_next;
  955.     }
  956. }
  957.  
  958. static int check_hdrs(channame, list)
  959. char        *channame;
  960. LIST_BPT    *list;
  961. {
  962.     LIST_BPT    *ix;
  963.  
  964.     while (list != NULL) {
  965.         ix = headers_all;
  966.         while (ix != NULL
  967.                && strcmp(ix->li_name, list->li_name) != 0)
  968.             ix = ix->li_next;
  969.         if (ix == NULLIST_BPT)
  970.             perrstr("The channel '%s' has an unrecognised header '%s'.\n",
  971.                  channame,
  972.                  list->li_name);
  973.         list = list->li_next;
  974.     }
  975. }
  976.            
  977. /*   */
  978. static int yesorno(prompt)
  979. char    *prompt;
  980. {
  981.     if (monitoring == TRUE) {
  982.         printf("%s\n",prompt);
  983.         return FALSE;
  984.     }
  985.  
  986.     if (interactive == TRUE) {
  987.         char buf[BUFSIZ],
  988.              *ix;
  989.         int  noAnswer = TRUE,
  990.              answer = FALSE;
  991.  
  992.         /* output a yes/no query and return result */
  993.         while (noAnswer == TRUE) {
  994.             printf("%s (y/n) ?",prompt);
  995.             fgets(buf, BUFSIZ, stdin);
  996.             ix = buf;
  997.             while (*ix != NULL && isspace(*ix) != 0)
  998.                 ix++;
  999.             switch (*ix) {
  1000.                 case 'y':
  1001.                 case 'Y':
  1002.                 noAnswer = FALSE;
  1003.                 answer = TRUE;
  1004.                 break;
  1005.                 case 'n':
  1006.                 case 'N':
  1007.                 noAnswer = FALSE;
  1008.                 answer = FALSE;
  1009.                 break;
  1010.                 default:
  1011.                 break;
  1012.             }
  1013.         }
  1014.         return answer;
  1015.     } else {
  1016.         /* see if can do automatically and if so try it */
  1017.         pnewline();
  1018.         return TRUE;
  1019.     }
  1020. }
  1021.  
  1022. /*   */
  1023.  
  1024. static int doneMsg;
  1025.  
  1026. static int check_htable(name)
  1027. char    *name;
  1028. {
  1029.     /* check table with hardwired name 'name' exists */
  1030.     if (tb_nm2struct(name) == NULLTBL) {
  1031.         if (doneMsg == 0) {
  1032.             printf("Note that the following messages may or may not be fatal\nThis depends on the local requirements\n");
  1033.             doneMsg = 1;
  1034.         }
  1035.         perrstr("A table with the hardwired name '%s' is not present\n",
  1036.                name);
  1037.     } else if (verbose == TRUE)
  1038.         pok("Hardwired table", name);
  1039.         
  1040. }
  1041.  
  1042. static int check_hprog(name, defaultdir)
  1043. char    *name;
  1044. char    *defaultdir;
  1045. {
  1046.     struct stat statbuf;
  1047.     char    fullname[MAXPATHLENGTH];
  1048.  
  1049.     if (name[0] == '/')
  1050.         strcat(fullname, name);
  1051.     else
  1052.         sprintf(fullname, "%s/%s", defaultdir, name);
  1053.  
  1054.     if (stat(fullname, &statbuf) != OK)
  1055.         perrstr("The hardwired program %s does not exist\n",
  1056.                  fullname);
  1057.     else if (!(statbuf.st_mode & S_IEXEC)) 
  1058.         perrstr("The hardwired program %s is not executable\n",
  1059.              fullname);
  1060.     else if (statbuf.st_uid != ppuid)
  1061.         perrstr("WARNING hardwired program %s is not owned by '%s'\n",
  1062.              fullname,
  1063.              pplogin);
  1064.     else if (verbose == TRUE) 
  1065.         /* print info */
  1066.         pok ("Hardwired program", name);
  1067. }
  1068.  
  1069.     
  1070. static int check_hchan(name)
  1071. char    *name;
  1072. {
  1073.     
  1074.     if (ch_nm2struct(name) == NULLCHAN) {
  1075.         if (doneMsg == 0) {
  1076.             printf("Note that the following messages may or may not be fatal\nThis depends on the local requirements\n");
  1077.             doneMsg = 1;
  1078.         }
  1079.         perrstr("A channel with the hardwired name '%s' is not present\n",
  1080.                name);
  1081.     } else if (verbose == TRUE) 
  1082.         pok("Hardwired channel", name);
  1083. }
  1084.  
  1085. static int check_hbp(name)
  1086. char    *name;
  1087. {
  1088.     LIST_BPT    *ix = bodies_all;
  1089.  
  1090.     while (ix != NULL 
  1091.            && strcmp(name, ix->li_name) != 0)
  1092.         ix = ix->li_next;
  1093.     if (ix == NULLIST_BPT) {
  1094.         if (doneMsg == 0) {
  1095.             printf("Note that the following messages may or may not be fatal\nThis depends on the local requirements\n");
  1096.             doneMsg = 1;
  1097.         }
  1098.         perrstr("A bodypart with the hardwired name '%s' is not present\n",
  1099.                name);
  1100.     } else if (verbose == TRUE)
  1101.         pok("Hardwired body part", name);
  1102. }        
  1103.  
  1104. static int check_hhdr(name)
  1105. char    *name;
  1106. {
  1107.     LIST_BPT    *ix = headers_all;
  1108.  
  1109.     while (ix != NULL 
  1110.            && strcmp(name, ix->li_name) != 0)
  1111.         ix = ix->li_next;
  1112.     if (ix == NULLIST_BPT) {
  1113.         if (doneMsg == 0) {
  1114.             printf("Note that the following messages may or may not be fatal\nThis depends on the local requirements\n");
  1115.             doneMsg = 1;
  1116.         }
  1117.         perrstr("A header with the hardwired name '%s' is not present\n",
  1118.                name);
  1119.     } else if (verbose == TRUE)
  1120.         pok("Hardwired header", name);
  1121. }        
  1122.  
  1123. static int check_hardwired()
  1124. {
  1125.     extern char    *submit_prog, *uucpin_chan, *local_822_chan, 
  1126.             *alias_tbl, *channel_tbl, 
  1127.             *list_tbl, *user_tbl, *or_tbl, *or2rfc_tbl, 
  1128.             *rfc2or_tbl, *chan_auth_tbl, *rfc1148gateway_tbl, 
  1129.             *mta_auth_tbl, *user_auth_tbl, *qmgr_auth_tbl,
  1130.             *hdr_822_bp, *hdr_p2_bp, *hdr_ipn_bp, *ia5_bp;
  1131.     if (verbose == TRUE)
  1132.         printf("\nChecking the various hardwired names (static.c)\n\n");
  1133.     if (verbose == TRUE) {
  1134.         printf("Note that the following messages may or may not be fatal\nThis depends on the local requirements\n");
  1135.         doneMsg = 1;
  1136.     } else
  1137.         doneMsg = 0;
  1138.  
  1139.     check_hprog(submit_prog, cmddfldir);
  1140.     check_hchan(uucpin_chan);
  1141.     check_hchan(local_822_chan);
  1142.     check_htable(alias_tbl);
  1143.     check_htable(channel_tbl);
  1144.     check_htable(list_tbl);
  1145.     check_htable(user_tbl);
  1146.     check_htable(or_tbl);
  1147.     check_htable(or2rfc_tbl);
  1148.     check_htable(rfc2or_tbl);
  1149.     check_htable(chan_auth_tbl);
  1150.     check_htable(mta_auth_tbl);
  1151.     check_htable(user_auth_tbl);
  1152.     check_htable(rfc1148gateway_tbl);
  1153.     check_hhdr(hdr_822_bp);
  1154.     check_hhdr(hdr_p2_bp);
  1155.     check_hhdr(hdr_ipn_bp);
  1156.     check_hbp(ia5_bp);
  1157.     check_htable(qmgr_auth_tbl);
  1158. }
  1159.  
  1160. /*   */
  1161. static int  makedirectory(name, mode)
  1162. char        *name;
  1163. int    mode;
  1164. {
  1165.     char    *ix, *last;
  1166.     struct stat statbuf;
  1167.  
  1168.     last = ix = name;
  1169.     if (*ix == '/') ix++;
  1170.     while (*ix != '\0') {
  1171.         while (*ix != '\0' && *ix != '/') ix++;
  1172.         if (*ix != '\0' ) {
  1173.             *ix = '\0';
  1174.             if (stat(name, &statbuf) != OK) {
  1175.                 if (mkdir(name, mode) != 0) {
  1176.                     printf("!*!* Failed to make directory %s\n",name);
  1177.                     *ix = '/';
  1178.                     return;
  1179.                 } else 
  1180.                     printf("---> Made directory %s\n",name);
  1181.             }
  1182.             *ix = '/';
  1183.             last = ix;
  1184.             ix++;
  1185.         } else {
  1186.             if (ix != last + 1) {
  1187.                 /* doesn't end with / so check last segment */
  1188.                 if (stat(name, &statbuf) != OK) {
  1189.                     if (mkdir(name, mode) != 0) 
  1190.                         printf("!*!* Failed to make directory %s\n",name);
  1191.                     else
  1192.                         printf("---> Made directory %s\n",name);
  1193.                 }
  1194.                 /* reached end so return */
  1195.             }
  1196.             return;
  1197.         }
  1198.     }
  1199.  
  1200. /*    if (mkdir(name, mode) != 0)
  1201.         printf("!*!* Failed to make directory %s\n",name);
  1202.     else
  1203.         printf("---> Made directory %s\n",name);*/
  1204. }
  1205.  
  1206. static int changeowner(file, uid, gid)
  1207. char        *file;
  1208. int        uid, gid;
  1209. {
  1210.     if (chown(file, uid, gid) != 0)
  1211.         printf("!*!* Failed to change owner of %s to %o and group %o\n",
  1212.                file, uid, gid);
  1213.     else
  1214.         printf("---> Changed owner of %s to %o\n",
  1215.                file, uid);
  1216. }
  1217.  
  1218. static int changemode(file, mode)
  1219. char        *file;
  1220. int        mode;
  1221. {
  1222.     if (chmod(file,mode) != 0) 
  1223.         printf("!*!* Failed to change mode of %s to %o\n",
  1224.                file, mode);
  1225.     else
  1226.         printf("---> Changed mode of %s to %o\n",
  1227.                file,mode);
  1228. }
  1229.  
  1230. /*   */
  1231. /* output routines */
  1232.  
  1233. pnewline()
  1234. {
  1235.     if (verbose == TRUE)
  1236.         printf("\n");
  1237. }
  1238.  
  1239. #ifdef lint
  1240. /*VARARGS1*/
  1241. static void perrstr(str)
  1242. char *str;
  1243. {
  1244.     perrstr(str);
  1245. }
  1246. #else
  1247. static void perrstr(va_alist)
  1248. va_dcl
  1249. {
  1250.     char buf[BUFSIZ];
  1251.     va_list ap;
  1252.  
  1253.     va_start (ap);
  1254.     _asprintf (buf, NULLCP, ap);
  1255.     fputs (buf, stdout);
  1256.     va_end (ap);
  1257. }
  1258. #endif
  1259.  
  1260. #define tab    20
  1261. static int pok(one,two)
  1262. char    *one,
  1263.     *two;
  1264. {
  1265.     if (verbose == TRUE) {
  1266.         ptabss(one,two);
  1267.         pnewline();
  1268.     }
  1269. }
  1270.  
  1271. static int ptabss(one,two)
  1272. char    *one,
  1273.     *two;
  1274. {
  1275.     if (verbose == TRUE)
  1276.         printf("%-*s: %s\n",tab, one, two);
  1277. }
  1278.  
  1279. static int ptabsd(one,two)
  1280. char    *one;
  1281. int    two;
  1282. {
  1283.     if (verbose == TRUE)
  1284.         printf("%-*s: %d\n",tab,one,two);
  1285. }
  1286.  
  1287. static int check_822address(str)
  1288. char    *str;
  1289. {
  1290.     ADDR    *ad;
  1291.     RP_Buf    rp;
  1292.     ad = adr_new(str, AD_822_TYPE, 0);
  1293. #ifdef UKORDER
  1294.     if (rp_isbad(ad_parse(ad, &rp, CH_UK_PREF)))
  1295. #else
  1296.     if (rp_isbad(ad_parse(ad, &rp, CH_USA_PREF)))
  1297. #endif
  1298.         perrstr("rfc822 required address '%s' is an invalid address (reason = '%s').\n",
  1299.              str,
  1300.              ad->ad_parse_message);
  1301.     adr_free(ad);
  1302. }
  1303.         
  1304. static void check_dsap ()
  1305. {
  1306.     int pid, cpid;
  1307.  
  1308.     if ((pid = tryfork ()) == -1)
  1309.         return;
  1310.     if (pid == 0) {        /* child */
  1311.         dsap_init((char ***)NULL, (int *) NULL);
  1312.         _exit (0);
  1313.     }
  1314.     else {
  1315. #ifdef SYSV
  1316.         int w;
  1317.         while ((cpid = wait (&w)) != pid && cpid != NOTOK)
  1318.             continue;
  1319. #else
  1320.         union wait w;
  1321.         while ((cpid = wait (&w.w_status)) != pid && cpid != NOTOK)
  1322.             continue;
  1323. #endif
  1324.         if (!WIFSIGNALED(w) && WEXITSTATUS(w) == 0) {
  1325.             dsap_init((char ***)NULL, (int *) NULL);
  1326.             return;
  1327.         }
  1328.         perrstr("dsap error: probably quipu oid tables not installed?\n");
  1329.     }
  1330. }
  1331.